--extend UserData

local string_split = string.split
local string_find = string.find
local string_sub = string.sub

local UserData = import(".UserData")

function UserData:initUserdataAttr()
    if self._propTableTemp then return end

    self._propTableTemp = {} -- prop表倒置转存，以name为键，ID为值
    for _,v in pairs( GD:getPropConfigs() ) do
        local name = v.name
        --v.ID = k
        self._propTableTemp[ name ] = v
    end

    self._oldCaledValue = {} -- 保存的旧属性
    self._caledValue = {} -- 算完之后的总属性
    self._talentAtcritrt = 0 -- 天赋暴击点数
    self._talentAthitrt = 0 -- 天赋命中点数
    self._talentAtdodgert = 0 -- 天赋闪避点数
end


function UserData:getTalentAtcritrt()
    return self._talentAtcritrt
end

function UserData:getTalentAthitrt()
    return self._talentAthitrt
end

function UserData:getTalentAtdodgert()
    return self._talentAtdodgert
end


function UserData:clearUserdataAttr()
end



-- 帮助函数：格式化属性变动文本
function UserData:_formatChangedAttr( attrId, attrNum ) -- attrId - Prop表Id
    local positiveSign = 0 < attrNum and "+" or "-"

    attrId = tonumber( attrId )
    attrNum = math.abs( tonumber( attrNum ) )

    local propConf = GD:getPropConfig( attrId )
    assert( propConf, " ---------->>>>>> prop表中取不到配置，id=" .. attrId )

    local format = tonumber( propConf.format )
    local formatedAttrNum = ""
    if 1 == format then -- 整数
        formatedAttrNum = math.floor( attrNum )
    elseif 2 == format then -- %
        formatedAttrNum = attrNum/10000*100 .. "%"
    elseif 3 == format or 4 == format then
        formatedAttrNum = attrNum/1000
    end
    return table.concat( { L(propConf.name), positiveSign, formatedAttrNum } )
end




-- 帮助函数：格式化属性
function UserData:formatAttr( attrId, attrNum ) -- attrId - Prop表Id
    attrId = tonumber( attrId )
    attrNum = tonumber( attrNum )

    local propConf = GD:getPropConfig( attrId )
    assert( propConf, " ---------->>>>>> prop表中取不到配置，id=" .. attrId )

    local format = tonumber( propConf.format )
    local formatedAttrNum = ""
    if 1 == format then -- 整数
        formatedAttrNum = math.floor( attrNum )
    elseif 2 == format then -- %
        formatedAttrNum = attrNum/10000*100 .. "%"
    elseif 3 == format or 4 == format then
        formatedAttrNum = attrNum/1000
    end
    return L(propConf.name), formatedAttrNum, L(propConf.name) .. "+ " .. formatedAttrNum
end
-- 帮助函数：将 eachAttr 属性合并到 attrListTemp 中
function UserData:MergeAttr( attrListTemp, eachAttr )
    if attrListTemp[ eachAttr[1] ] then
        attrListTemp[ tonumber( eachAttr[1] ) ] = attrListTemp[ eachAttr[1] ] + tonumber( eachAttr[2] )
    else
        attrListTemp[ tonumber( eachAttr[1] ) ] = tonumber( eachAttr[2] )
    end
end



-- 统计userdata会用的所有属性列表
function UserData:calUserdataAttr()
    self._oldCaledValue = clone( self._caledValue )
    -- dump( self._oldCaledValue, " ------------------>>>>>> 旧属性" )

    local totalAttrList = {} -- 总属性列表
    totalAttrList = self:calEachUserdataAttr()
    -- dump( totalAttrList, " ------------------>>>>>> totalAttrList " )

    local p = {}
    p.level = function()
        return self.player.level
    end
    for k,v in pairs( GD:getPropConfigs() ) do
        p[v.name] = function()
            return totalAttrList[ tonumber( v.ID ) ] or 0
        end
        p[ "set_" .. v.name ] = function( _, param )
            self._caledValue[ v.name ] = param or 0
        end
    end
    setmetatable(p,{__index = function(tab, key)
        return function() return 0 end
    end})

    local formula = app:loadResScript("scripts.battle.formula")
    if formula then
        self._talentAtcritrt, self._talentAthitrt, self._talentAtdodgert = caclProp( p ) -- formula.caclProp
    end
    -- dump( self._caledValue, " ------------------>>>>>> 新属性" )

    -- 以下：做属性变数提示：暂时不需要此段逻辑
    -- if next( self._oldCaledValue ) then -- 之前已经算过属性了？
    --     local removedAttrList = {} -- 丢失的属性列表
    --     local addedAttrList = {} -- 新增的属性列表
    --     local changedAttrList = {} -- 属性发生变动的列表

    --     for k,v in pairs( self._oldCaledValue ) do
    --         if not self._caledValue[k] then
    --             table.insert( removedAttrList, { k, -v } )
    --         end
    --     end
    --     for k,v in pairs( self._caledValue ) do
    --         if not self._oldCaledValue[k] then
    --             table.insert( addedAttrList, { k, v } )
    --         else
    --             local offAttrNum = self._caledValue[k] - self._oldCaledValue[k] -- 属性变动差值
    --             if 0 ~= offAttrNum then
    --                 table.insert( changedAttrList, { k, offAttrNum } )
    --             end
    --         end
    --     end

    --     -- dump( removedAttrList, " ------------------>>>>>> 丢失的属性" )
    --     -- dump( addedAttrList, " ------------------>>>>>> 新增的属性" )
    --     -- dump( changedAttrList, " ------------------>>>>>> 变动的属性" )

    --     if 0 < #removedAttrList or 0 < #addedAttrList or 0 < #changedAttrList then
    --         local tipsStrList = {}
    --         for i,v in ipairs( removedAttrList ) do
    --             table.insert( tipsStrList, self:_formatChangedAttr( self._propTableTemp[ v[1] ].ID, v[2] ) )
    --         end
    --         for i,v in ipairs( addedAttrList ) do
    --             table.insert( tipsStrList, self:_formatChangedAttr( self._propTableTemp[ v[1] ].ID, v[2] ) )
    --         end
    --         for i,v in ipairs( changedAttrList ) do
    --             table.insert( tipsStrList, self:_formatChangedAttr( self._propTableTemp[ v[1] ].ID, v[2] ) )
    --         end
    --         tipsStrList = table.randomCnt( tipsStrList )
    --         for i,v in ipairs( tipsStrList ) do
    --             display.pushToast( v )
    --         end
    --     end
    -- end
end

-- 初始化player的显示属性列表
function UserData:initShownProp()
    self._showAttrList = {}
    local classTemp = tostring( self.player.classID )
    local propShowConfs = GD:querypropShow()

    for i,v in ipairs( propShowConfs ) do
        if string_find( v.roleSuit, classTemp ) then
            local _, attrstr = self:formatAttr( self._propTableTemp[ v.propName ].ID, 0  )
            table.insert( self._showAttrList, { v.propName, attrstr } )
        end
    end
end
function UserData:getShownProp()
    if not self._showAttrList then
        self:initShownProp()
    end
    for i,v in ipairs( self._showAttrList ) do
        if self._caledValue[ v[1] ] then
            local _, attrStr =  self:formatAttr( self._propTableTemp[ v[1] ].ID, self._caledValue[ v[1] ] )
            v[2] = attrStr
        end
    end
    return self._showAttrList
end

function UserData:calAttrByKey(dict, level)
    -- dump(dict, "UserData:calAttrByKey")
    local ret = {}
    local p = {}
    p.level = function()
        return level or 1
    end
    for k,v in pairs( dict ) do
        p[k] = function()
            return tonumber(v) or 0
        end
    end
    setmetatable(p,
        {__index = function(tab, key)
            local sIndex, endIndex = string_find(key, "_")
            if sIndex ~= nil then
                -- 属于set方法
                local attrKey = string_sub(key, endIndex+1, -1)
                return function(t, value)
                    ret[attrKey] = value
                end
            else
                return function() return 0 end
            end
        end})

    local formula = app:loadResScript("scripts.battle.formula")
    if formula then
        caclProp( p ) -- formula.caclProp
    end
    -- dump(ret, "UserData:calAttrByKey ret")
    return ret
end


---------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>> 通用方法：计算一个 player 的全属性方法
function UserData:calEachUserdataAttr( class, specialistID, equips, equipGrids, talents, mounts, mapBuffs )
    local totalAttrList = {} -- 总属性列表

    local playerAttrList = self:calPlayerAttr( class )
    -- dump( playerAttrList, " -------->>> 裸装备属性 " )
    for k,v in pairs( playerAttrList ) do
        self:MergeAttr( totalAttrList, { k, v } )
    end

    local talentAttrList = self:calTalentAttr( talents, specialistID )
    -- dump( talentAttrList, " -------->>> 天赋属性加成 " )
    for k,v in pairs( talentAttrList ) do
        self:MergeAttr( totalAttrList, { k, v } )
    end

    local equipedAttrList = self:calPlayerEquipedAttr( equips, equipGrids )
    -- dump( equipedAttrList, " -------->>> 装备属性加成 " )
    for k,v in pairs( equipedAttrList ) do
        self:MergeAttr( totalAttrList, { k, v } )
    end

    local suitedEquipedAttrList = self:calPlayerSuitedEquipedAttr( equips, specialistID )
    -- dump( suitedEquipedAttrList, " -------->>> 套装属性加成 " )
    for k,v in pairs( suitedEquipedAttrList ) do
        self:MergeAttr( totalAttrList, { k, v } )
    end

    local activatedMountsAttrList = self:calActivatedMountsAttr( mounts )
    -- dump( activatedMountsAttrList, " -------->>> 激活坐骑属性加成 " )
    for k,v in pairs( activatedMountsAttrList ) do
        self:MergeAttr( totalAttrList, { k, v } )
    end

    local mapBuffsAttrList = self:calMapBuffsAttr( mapBuffs )
    -- dump( mapBuffsAttrList, " -------->>> mapBuff属性加成 " )
    for k,v in pairs( mapBuffsAttrList ) do
        self:MergeAttr( totalAttrList, { k, v } )
    end

    return totalAttrList
end

-- 计算人物裸身属性
function UserData:calPlayerAttr( class )
    class = class or self:getClass() -- 默认取自己

    local protagonist_baseConf = GD:queryProBase( class ):getValues()
    assert( protagonist_baseConf, " ---------------------->>>>> player_base 表取不到职业数据，id = " .. self:getClass() )

    local playerAttrList = {}
    for k,v in pairs( protagonist_baseConf ) do
        local propID = self._propTableTemp[ k ] and self._propTableTemp[ k ].ID or 0
        if 0 ~= propID then
            playerAttrList[propID] = tonumber( v )
        end
    end
    return playerAttrList
end

-- 计算选择的天赋属性加成
function UserData:calTalentAttr( talents, specialistID )
    talents = talents or self.talents
    specialistID = specialistID or self:getCurSpecTypeId()

    local talentAttrList = {}
    for k,v in pairs( talents ) do
        for k2,v2 in pairs( v:getSkillAttr( specialistID ) ) do
            self:MergeAttr( talentAttrList, { k2, v2 } )
        end
    end
    return talentAttrList
end

-- 计算人物身上装备属性
function UserData:calPlayerEquipedAttr( equips, equipGrids )
    equips = equips or self.equips
    equipGrids = equipGrids or self._equipGrids

    local equipedAttrList = {}
    local equipGrid = nil
    for k,v in pairs( equips ) do
        equipGrid = equipGrids[ v:getPos() ]
        if equipGrid then
            local strengthenLv = equipGrid:getStrengthLevel() or 0
            for k2,v2 in pairs( v:getTotalAttr( strengthenLv ) ) do
                self:MergeAttr( equipedAttrList, { k2, v2 } )
            end
        end
    end
    return equipedAttrList
end

-- 计算人物身上装备组成的套装属性加成
function UserData:calPlayerSuitedEquipedAttr( equips, specialistID )
    equips = equips or self.equips
    specialistID = specialistID or self:getCurSpecTypeId()

    local suitedEquipedAttrList = {}
    local suitList = {}
    for k,v in pairs( equips ) do
        local suit = tonumber( v:getSuit() )
        if suit then -- 有套装？
            if suitList[ suit ] then
                suitList[ suit ] = suitList[ suit ] + 1
            else
                suitList[ suit ] = 1
            end
        end
    end
    for k,v in pairs( suitList ) do
        -- print( " --------------------->>>>>>> 套装ID：" .. k .. " ;件数：".. v )
        local suitConf = GD:queryEquipSuitById( k )
        for i = 1, 5 do -- 配置表中套装件数组合
            if suitConf["num"..i] and v >= tonumber( suitConf["num"..i] ) then
                local specialistIDAttrList = string_split( suitConf["propAdd"..i], ";" )
                local specialistIDAttrIdx = 0
                for i2,v2 in ipairs( specialistIDAttrList ) do
                    local specialistIDEnd = string_find( v2, "|" )
                    local specialistIDTemp = string_sub( v2, 1, specialistIDEnd - 1 )
                    -- print( " --------------------->>>>>>> 解析出来的专精id " .. tostring( specialistID ) )
                    if tonumber( specialistID ) == tonumber( specialistIDTemp ) then
                        specialistIDAttrIdx = i2
                        break
                    end
                end
                local specialistIDAttrStr = specialistIDAttrList[ specialistIDAttrIdx ]
                local attrStr = string_split( specialistIDAttrStr, "|" )[2]
                local attrList = string_split( attrStr, "&" )
                for _,v3 in ipairs( attrList ) do
                    local attrPair = string_split( v3, ":" ) -- 属性对 { propId, value }
                    self:MergeAttr( suitedEquipedAttrList, { tonumber( attrPair[1] ), tonumber( attrPair[2] ) } )
                end
            end
        end
    end
    -- dump( suitedEquipedAttrList, " --------------------->>>>>>> 套装属性：" )
    return suitedEquipedAttrList
end

-- 计算拥有的坐骑属性加成
function UserData:calActivatedMountsAttr( activatedMounts )
    activatedMounts = activatedMounts or self:getActivatedMounts()

    local activatedMountsAttrList = {}
    for k,v in pairs( activatedMounts ) do
        for k,v in pairs( v:getAttrs() ) do -- 坐骑原始属性
            self:MergeAttr( activatedMountsAttrList, { k, v } )
        end
        for k,v in pairs( v:getSkillAttr() ) do -- 坐骑技能提供的属性
            self:MergeAttr( activatedMountsAttrList, { k, v } )
        end
    end
    return activatedMountsAttrList
end

-- 计算mapBuffs的属性加成
function UserData:calMapBuffsAttr( mapBuffs )
    mapBuffs = mapBuffs or self:getMapBuffs()

    local curTime = math.floor(app.session:getServerTime() or app:getTime())
    local mapBuffsAttrList = {}
    for _, buff in pairs( mapBuffs ) do
        if buff.destroyTime - curTime > 0 then -- 有效时间之内？
            local mapBuffConf = GD:getBuffConfig( buff.tid )
            if mapBuffConf and mapBuffConf.prop and "" ~= mapBuffConf.prop then -- 存在有效属性
                local mapbuffList = string_split( mapBuffConf.prop, ";" )
                for i, v in ipairs( mapbuffList ) do
                    local attrPair = string_split( v, "|" ) -- 属性对 { propId, value }
                    self:MergeAttr( mapBuffsAttrList, { tonumber( attrPair[1] ), tonumber( attrPair[2] ) } )
                end
            end
        end
    end
    return mapBuffsAttrList
end

return UserData
